function DatagridUtil(grid, options) {
	// 表格
	this.grid = grid;
	
	// 配置对象
	options = options || {};
	// 是否深度修改配置，默认true
	var recursionextend = (options.recursionExtend != false ? true : false);
	this.options = $.extend(recursionextend, {
		// 功能ID，必填
		funcid : null,
		// 顶部工具栏选择器
		toolbar : '.main-toolbar',
		// 是不是回收站
		isRecycle : false,
		// 加载功能按钮URL
		funcUrl : __ctx + '/main/findAuthByParentfuncAndFunctype.xhtml',
		// 是否开启展开查询
		isOpenQuery : true,
		// 展开查询内容选择器
		developQuery : '.main-develop-query',
		// 是否开启查看详情
		isOpenDetails : true,
		// 详情方法
		detailsMethod : 'queryDetail',
		// 回收站恢复方法
		restoreMethod : 'recycleRestore',
		// 回收站删除方法
		deleteMethod : 'recycleDelete',
		// 回收站方法名称
		recycleMethodName : 'recycle',
		// 更新实体状态方法名称，updateEntitystateUrl不为空时生效
		updateEntitystateMethodName : {
			del : {
				oper : 'del', 
				msg : '确定要删除吗？'
			},
			recycleRestore : {
				oper : 'restore', 
				msg : '确定要恢复吗？'
			},
			recycleDelete : {
				oper : 'delete', 
				msg : '确定要删除吗？'
			}
		},
		// 更新实体状态地址
		updateEntitystateUrl : null,
		/**
		 * 验证规则，数组
		 * methodname 按钮类型
		 * fields 条件字段
		 * conditions 条件值；null时所有将返回满足
		 * ismultiple 是否支持多选
		 * allownull 允许为null
		 */
		validateRules : null,
		/**
		 * 验证配置
		 * ignoretypes 忽略按钮类型
		 * fields 全局条件字段
		 */
		validateOptions : null
	}, options);
	// 初始化
	this.__init();
}
DatagridUtil.prototype = {
	// 构造函数
	consructor : DatagridUtil,
	// 初始化函数
	__init : function() {
		this.loadFuncButton();
		
		var invokeobj = this;
		var originalSelectchanged = this.grid.selectchanged;
		this.grid.selectchanged = function(e) {
			invokeobj.enabledToolbarButtons(e.rows);
			if (originalSelectchanged && typeof(originalSelectchanged) == 'function') {
				originalSelectchanged.call(datagrid, e);
			}
		}
	},
	/**
	 * 加载功能按钮
	 */
	loadFuncButton : function() {
		var options = this.options || {};
		this.toolbarButtons = new Array();
		var invokeobj = this;
		// 按钮配置
		if (options.isOpenDetails) {
			// 添加查看详情按钮
			invokeobj.toolbarButtons.push({entityid : 1, funcname : '查看详情', functype : 3, showicon : null, showorder : 0, invokemethod : options.detailsMethod, rightsupport : true, notopsupport : true});
		}
		if (options.isOpenQuery) {
			// 添加展开查询按钮
			invokeobj.toolbarButtons.push({entityid : 2, funcname : '展开查询', functype : 3, showicon : null, showorder : 999, invokemethod : null, rightsupport : false});
		}
		var funcid = options.funcid || null;
		if (!funcid) {
			invokeobj.createFuncButton();
			return;
		}
		// 判断当前位置
		if (options.isRecycle) {
			// 回收站
			invokeobj.toolbarButtons.push({entityid : 3, funcname : '恢复', functype : 3, showicon : null, showorder : 997, invokemethod : options.restoreMethod, rightsupport : true});
			invokeobj.toolbarButtons.push({entityid : 4, funcname : '删除', functype : 3, showicon : null, showorder : 998, invokemethod : options.deleteMethod, rightsupport : true});
			invokeobj.toolbarButtons.push({entityid : 5, funcname : '返回', functype : 3, showicon : null, showorder : 1000, invokemethod : null, rightsupport : false});
			invokeobj.createFuncButton();
		} else {
			// 正常
			$.post(options.funcUrl, {parentfunc : funcid, functype : [3]}, function(result) {
				if (result.status) {
					var funcButtons = result.result || null;
					if (funcButtons && funcButtons.length >= 0) {
						invokeobj.toolbarButtons = invokeobj.toolbarButtons.concat(funcButtons);
					}
					if (!invokeobj.toolbarButtons || invokeobj.toolbarButtons.length <= 0) {
						return;
					}
					invokeobj.createFuncButton();
				}
			})
		}
	},
	/**
	 * 创建按钮
	 */
	createFuncButton : function() {
		if (!this.toolbarButtons || this.toolbarButtons.length <= 0) {
			return;
		}
		var options = this.options || {};
		var $toolbar = $(options.toolbar);
		var $developQuery = $(options.developQuery);
		var invokeobj = this;
		// 生成操作按钮
		var hasToolbar = ($toolbar && $toolbar.length > 0);
		var hasDevelopQuery = ($developQuery && $developQuery.length > 0);
		// 冒泡排序
		var buttons = this.toolbarButtons || new Array();
		for(var i = 0; i < buttons.length - 1; i++){
            for(var j = 0; j < buttons.length - 1 - i; j++){
                if(buttons[j].showorder > buttons[j + 1].showorder){
                    var temp = buttons[j + 1];
                    buttons[j + 1]=buttons[j];
                    buttons[j] = temp;
                }
            }
        }
		this.toolbarButtons = buttons;
		$.each(this.toolbarButtons, function(toolbarIndex, toolbarButton) {
			// 处理按钮方法
			if (options.recycleMethodName == this.invokemethod) {
				// 回收站
				this.method = function(e) {
					var iframe = window.parent.document.getElementById('iframe-content');
					iframe.src = iframe.src + '&recycle=true';
				}
			} else if (this.entityid == 2) {
				// 展开查询
				if (hasDevelopQuery) {
					this.method = function() {
						$developQuery.toggle();
						invokeobj.grid.doLayout();
					}
				}
			} else if (this.entityid == 5) {
				// 回收站返回
				this.method = function(e) {
					var iframe = window.parent.document.getElementById('iframe-content');
					iframe.src = iframe.src.replace('&recycle=true', '');
				}
			} 
			if (this.invokemethod && options.recycleMethodName != this.invokemethod) {
				// 功能按钮方法加入前置方法
				var invokemethod;
				if (options.updateEntitystateUrl && options.updateEntitystateMethodName && options.updateEntitystateMethodName.hasOwnProperty(this.invokemethod)) {
					var methodoptions = options.updateEntitystateMethodName[this.invokemethod];
					invokemethod = function(e) {
						top.search.confirm({content : methodoptions.msg, funl : function() {
							$.post(options.updateEntitystateUrl, {entityids : e.ids, oper : methodoptions.oper}, function(result) {
								if (result.status) {
									top.search.info({content : '操作成功', funl : function() {
										grid.reload();
									}});
								} else {
									SearchUtils.msg(result.result);
								}
							})
						}});
					}
				} else {
					invokemethod = searchComponents.findMethod(this.invokemethod);
				}
				if (invokemethod) {
					this.method = function(e) {
						// 获取选中行
						var rows = null;
						if (e) {
							rows = [e.origin];
						} else {
							rows = invokeobj.grid.getSelecteds();
						}
						// 获取选中行ID
						var idArr = new Array();
						var idField = invokeobj.grid.idField;
						$.each(rows, function() {
							idArr.push(this.record[idField]);
						})
						invokemethod.call(null, {ids : idArr.join(','), rows : rows});
					}
				}
			}
			// 生成右键菜单
			if (this.rightsupport && invokeobj.grid) {
				var enableValidate = null;
				if (options.validateRules) {
					enableValidate = function(e) {
						if (toolbarButton.invokemethod == options.recycleMethodName) {
							return;
						}
						e.result = invokeobj.validateButtons(e);
					}
				}
				invokeobj.grid.addContextMenuItem(this.entityid, 'menu', this.funcname, '', this, true, true, null, null, this.method, enableValidate, null);
			}
			if (this.notopsupport || !hasToolbar) {
				return true;
			}
			this.tophtml = $('<input class="search-button blue main-toolbar-button" type="button" value="' + this.funcname + '">');
			if (this.method) {
				var method = this.method;
				this.tophtml.on('click', function() {
					method.call(null);
				})
			}
			if (this.invokemethod && this.invokemethod != options.recycleMethodName && !invokeobj.validateButtons({custom : this, origin : []})) {
				this.tophtml.off('click');
				this.tophtml.addClass('disabled').removeClass('blue');
			}
			$toolbar.append(this.tophtml);
		})
	},
	/**
	 * 启用按钮
	 * @param rows 数据数组
	 */
	enabledToolbarButtons : function(rows) {
		var invokeobj = this;
		var options = this.options;
		if (this.toolbarButtons && this.toolbarButtons.length > 0 && options.validateRules) {
			$.each(this.toolbarButtons, function() {
				if (this.notopsupport || !this.invokemethod || this.invokemethod == options.recycleMethodName) {
					return true;
				}
				if (!invokeobj.validateButtons({custom : this, origin : rows})) {
					this.tophtml.off('click');
					this.tophtml.addClass('disabled').removeClass('blue');
				} else if (this.tophtml.hasClass('disabled')) {
					var method = this.method;
					this.tophtml.on('click', function() {
						method.call(null);
					})
					this.tophtml.removeClass('disabled').addClass('blue');
				}
			})
		}
	},
	 /**
     * 校验功能按钮是否可用
     * @param e 原始参数
     */
    validateButtons : function(e) {
    	var validateOptions = this.options.validateOptions || {};
    	if (validateOptions.ignoretypes && Array.isArray(validateOptions.ignoretypes) 
			&& validateOptions.ignoretypes.indexOf(e.custom.invokemethod) != -1) {
    		return true;
    	}
    	var conditions = this.options.validateRules;
    	var isvalidate = false;
    	var invokeobj = this;
    	if (conditions && conditions.length > 0) {
    		$.each(conditions, function(conditionIndex, condition) {
    			if (condition.methodname != e.custom.invokemethod) {
    				return true;
    			}
    			if (!condition.fields) {
    				// 使用全局条件字段
    				condition.fields = validateOptions.fields;
    			}
    			if (!condition.fields) {
    				return true;
    			}
    			isvalidate = invokeobj.validateButton(e, condition);
    			if (isvalidate) {
    				return false;
    			}
    		})
    	}
    	return isvalidate;
    },
    /**
     * 校验功能按钮是否可用
     * @param e 原始参数
     * @param conditions 条件数组
	 * 			methodname 按钮类型
	 * 			fields 条件字段
	 * 			conditions 条件值
	 *    		ismultiple 是否支持多选
	 *    		allownull 允许为null
     */
    validateButton : function(e, condition) {
    	if (!e.origin || e.origin.length <= 0) {
    		// 没有选中行
    		return condition.allownull ? true : false;
    	}
    	if (!condition.ismultiple && Array.isArray(e.origin) && e.origin.length > 1) {
    		// 不支持多选，但选中多行
    		return false;
    	}
    	var isvalidate = false;
		var origins = !Array.isArray(e.origin) ? [e.origin] : e.origin;
    	$.each(origins, function(originIndex, originVal) {
    		// 匹配数据是否满足，存在一个不满足，则检验失败
    		var isorigin = true;
    		if (condition.conditions && condition.conditions.length > 0) {
    			$.each(condition.conditions, function(conditionIndex, conditionVal) {
    				// 验证条件是否满足，存在一个满足，则匹配
    				var iscondition = true;
    				$.each(condition.fields, function(fieldIndex, fieldVal) {
    					// 验证值是否相等，存在一个不等，则不匹配，默认eq（相等）
    					if (/\:(ne|lt|le|ge|gt)$/.test(fieldVal)) {
    						var realfield = fieldVal.replace(/\:(ne|lt|le|ge|gt)$/, '');
    						if (/\:(ne)$/.test(fieldVal) && originVal.record[realfield] != conditionVal[fieldIndex]) {
    							return true;
    						} else if (/\:(lt)$/.test(fieldVal) && originVal.record[realfield] < conditionVal[fieldIndex]) {
    							return true;
    						} else if (/\:(le)$/.test(fieldVal) && originVal.record[realfield] <= conditionVal[fieldIndex]) {
    							return true;
    						} else if (/\:(gt)$/.test(fieldVal) && originVal.record[realfield] > conditionVal[fieldIndex]) {
    							return true;
    						} else if (/\:(ge)$/.test(fieldVal) && originVal.record[realfield] >= conditionVal[fieldIndex]) {
    							return true;
    						}
    					} else {
    						if (originVal.record[fieldVal] == conditionVal[fieldIndex]) {
        						return true;
        					}
    					}
    					iscondition = false;
    					return false;
            		})
            		if (iscondition) {
            			isorigin = true;
            			return false;
            		} else {
            			isorigin = false;
        				return true;
            		}
        		})
    		}
    		if (isorigin) {
    			isvalidate = true;
    			return true;
    		} else {
    			isvalidate = false;
    			return false;
    		}
    	})
    	return isvalidate;
    }
}

//常用组件
var searchComponents = new function() {
	// 私有属性
	this._controls = {};
	
	// 初始化完成执行函数
	this.initComplete = null;
	
	/**
	 * 初始化渲染
	 * 
	 * @param initComplete 初始化完成回调：有一个参数，所有解析完成的组件
	 */
	this.parse = function(initComplete) {
		var invoke = this;
		if (initComplete && typeof(initComplete) === "function") {
			invoke.initComplete = initComplete;
		}
		$('.search-component').each(function(index, elem) {
			var $elem = $(this);
			var id = $elem.attr('id');
			var cls = $elem.attr('class');
			
			// 控件已存在
			if (invoke._controls[id]) {
				return;
			}
			
			var cmpt = null;
			if (cls.containsClass("search-collapse")) {
				// 创建折叠
				cmpt = new Collapse();
			} else if (cls.containsClass("search-step")) {
				// 创建选项卡
				cmpt = new Step();
			}
			// 初始化
			if (cmpt && cmpt.initialize($elem)) {
				// 初始化完成
				invoke._controls[id] = cmpt;
				// 显示组件
				$elem.show();
			}
		})
		search.parse();
		if (invoke.initComplete && typeof(invoke.initComplete) === "function") {
			invoke.initComplete.apply(invoke, [invoke._controls]);
		}
	};
	
	/**
	 * 获取控件对象。
	 * @param ctlid 控件标识。
	 */
	this.get = function(ctlid) {
		return this._controls[ctlid];
	}
	
	/**
	 * 查找方法。
	 * @param name 方法名。
	 */
	this.findMethod = function(name) {
		try {
			if (name) {
				var method = eval(name);
				if (typeof(method) === "function") return method;
				
				console.log(name + " is not method.");
			}
		} catch (e) {
			console.log(e);
		}
		return null;
	};
	
	/**
	 * 执行方法
	 * @param method 方法
	 * @param invoke this指针
	 * @param params 参数数组
	 * @return 结果
	 */
	this.applyMethod = function(method, invoke, params) {
		if (method && typeof(method) == 'function') {
			return method.apply(invoke, params);
		}
		return undefined;
	};
	
	// 基础组件-开始
	function Control() {
		this.id = null;
		this.jqobj = null;
	};
	// 基础组件函数
	Control.prototype = {
		// 构造函数
		consructor : Control,
		// 初始化
		initialize : function(jqobj) {
			// 获取通用属性
			var invoke = this;
			invoke.id = jqobj.attr('id');
			invoke.jqobj = jqobj;
			// 获取配置信息
			var prototypes = invoke._prototypes;
			var opts = jqobj.data();
			var funcPrefix = 'func_', funcReg = new RegExp('^' + funcPrefix);
			for (var key in prototypes) {
				var isFunc = funcReg.test(key);
				var realKey = isFunc ? key.replace(funcPrefix, '') : key;
				if (opts[realKey] == undefined) {
					invoke[realKey] = prototypes[key];
					continue;
				}
				
				invoke[realKey] = isFunc ? searchComponents.findMethod(opts[realKey]) : opts[realKey];
			}
			return true;
		}
	};
	// 基础组件-结束
	
	// 折叠-开始
	function Collapse() {
		// 折叠项
		this.collapseItems = new Array();
		// 可配置属性
		this._prototypes = {
			single : false,
			func_click : null
		};
	};
	// 折叠函数
	Collapse.prototype = $.extend(new Control(), {
		// 构造函数
		consructor : Collapse,
		// 初始化
		initialize : function(jqobj) {
			var invoke = this;
			if (!Control.prototype.initialize.call(invoke, jqobj)) return false;
			
			// 初始化子级
			$.each(jqobj.find('.search-collapse-item'), function() {
				var collapseItem = new CollapseItem();
				if (collapseItem && collapseItem.initialize($(this))) {
					invoke.collapseItems.push(collapseItem);
				}
			})
			
			// 监听滚动事件，标题吸顶效果
			jqobj.on('scroll', function(e) {
				var $this = $(this);
				var collapsecsstop = invoke.jqobj.css('top');
				var collapsetop = (collapsecsstop == 0 ? 0 : parseInt(collapsecsstop.replace('px', '')));
				// 滚动条宽度
				var scrollbarWidth = $this[0].offsetWidth - $this[0].scrollWidth;
				if ($this.scrollTop() > 0) {
					// 查找应显示内容
					var $currentItem = null;
					$.each(invoke.collapseItems, function() {
						var $item = this.jqobj;
						if ($item.offset().top + $item.height() > 0) {
							$currentItem = $item;
							return false;
						}
						return true;
					})
					// 判断是否已经吸顶
					if ($currentItem.find('.search-collapse-fix-title-fill').length <= 0) {
						// 未吸顶时，进行吸顶操作
						// 移除其他标题吸顶
						jqobj.find('.search-collapse-fix-title').removeClass('search-collapse-fix-title').css({
							'right' : 0,
							'top' : 0
						});
						jqobj.find('.search-collapse-fix-title-fill').remove();
						// 当前标题添加吸顶
						$currentItem.find('.search-collapse-title').addClass('search-collapse-fix-title').css({
							'right' : 17,
							'top' : collapsetop
						});
						$currentItem.prepend('<div class="search-collapse-fix-title-fill"></div>')
					}
				} else {
					// 移除标题吸顶
					jqobj.find('.search-collapse-fix-title').removeClass('search-collapse-fix-title').css({
						'right' : 0,
						'top' : 0
					});
					jqobj.find('.search-collapse-fix-title-fill').remove();
				}
			})
			
			// 绑定事件
			$.each(invoke.collapseItems, function(index, collapseItem) {
				// 绑定标题单击事件
				collapseItem.jqobj.find('.search-collapse-title').bind({
					click : function(e) {
						// 自定义点击事件；返回结果为false时，将阻止折叠操作
						if (invoke.click && invoke.click.call(invoke, e, index) == false) {
							return;
						}
						var $this = $(this);
						var $content = collapseItem.jqobj.find('.search-collapse-content');
						if (invoke.single) {
							// 有且只有一个折叠项保持打开
							if (collapseItem.active) {
								return;
							}
							$.each(invoke.collapseItems, function() {
								if (!this.active) {
									return true;
								}
								this.jqobj.find('.search-collapse-content').hide();
								this.jqobj.find('.fa-angle-double-down').toggleClass('fa-angle-double-right fa-angle-double-down');
								// 更新打开状态
								this.active = !this.active;
							})
						}
						
						// 显示、隐藏
						$this.find('i').toggleClass('fa-angle-double-right fa-angle-double-down');
						$content.slideToggle('slow', 'swing');
						// 更新打开状态
						collapseItem.active = !collapseItem.active;
					}
				})
			})
			return true;
		},
		/**
		 * 根据ID查找折叠项
		 * @param id 折叠项ID
		 * @return 折叠项对象
		 */
		getCollapseItem : function(id) {
			var collapseItem = null;
			$.each(this.collapseItems, function() {
				if (this.id != id) {
					return true;
				}
				collapseItem = this;
				return false;
			})
			return collapseItem;
		}
	});
	// 折叠-结束
	
	// 折叠项-开始
	function CollapseItem() {
		// 可配置属性
		this._prototypes = {
			title : '',
			active : false
		};
	};
	// 折叠项函数
	CollapseItem.prototype = $.extend(new Control(), {
		// 构造函数
		consructor : CollapseItem,
		// 初始化
		initialize : function(jqobj) {
			var invoke = this;
			if (!Control.prototype.initialize.call(invoke, jqobj)) return false;
			
			// 创建标题节点
			var $creatTitle = $('<h2 class="search-collapse-title"><span></span><i class="fa"></i></h2>');
			$creatTitle.find('span').html(invoke.title);
			$creatTitle.find('.fa').addClass(invoke.active ? 'fa-angle-double-down' : 'fa-angle-double-right');
			// 创建内容节点
			var $creatContent = $('<div class="search-collapse-content"></div>');
			$creatContent.append(jqobj.children());
			if (!invoke.active) {
				$creatContent.hide();
			}
			jqobj.append($creatTitle);
			jqobj.append($creatContent);
			return true;
		},
		// 隐藏
		hide : function() {
			this.jqobj.hide();
		},
		// 显示
		show : function() {
			this.jqobj.show();
		},
		// 清空内容
		empty : function() {
			this.jqobj.find('.search-collapse-content').empty();
		},
		/**
		 * 尾部插入内容
		 * @param val 用于设定HTML内容的值
		 */
		append : function(val) {
			this.jqobj.find('.search-collapse-content').append(val);
		}
	});
	// 折叠项-结束
	
	// 选项卡-开始
	function Step() {
		// 选项卡项
		this.stepItems = new Array();
		// 当前步骤
		this.currentStepItem = null;
		// 按钮对象
		this.toolButtonObjs = new Array();
		// 按钮
		this.toolButtons = [
			{
				name : '上一步',
				addClass : 'btn btn-primary',
				sort : 100,
				click : function(stepitem) {
					this.setCurrentStepItem(stepitem.pre);
				},
				layout : function(stepitem) {
					return stepitem.index != 0;
				}
			}, {
				name : '保存',
				addClass : 'btn btn-default',
				sort : 200,
				click : function(stepitem) {
					searchComponents.applyMethod(this.save, this, [stepitem, 0]);
				},
				layout : function(stepitem) {
					if (this.isTab) {
						return true;
					} else {
						return stepitem.index >= (this.stepItems.length - 1);
					}
				}
			}, {
				name : '下一步',
				addClass : 'btn btn-success',
				sort : 300,
				click : function(stepitem) {
					this.setCurrentStepItem(stepitem.next);
				},
				layout : function(stepitem) {
					return stepitem.index < (this.stepItems.length - 1);
				}
			}
		];
		// 可配置属性
		this._prototypes = {
			// 是否选项卡
			isTab : true,
			// 按钮禁用时是否隐藏
			buttonDisabledIshide : false,
			// 初始化完成打开项索引
			active : 0,
			// 校验指定索引项表单；逗号分隔，null全部校验
			validateTab : null,
			// 保存按钮回调函数
			func_save : null
		};
	}
	// 选项卡函数
	Step.prototype = $.extend(new Control(), {
		// 构造函数
		consructor : Step,
		// 初始化
		initialize : function(jqobj) {
			var invoke = this;
			if (!Control.prototype.initialize.call(invoke, jqobj)) return false;
			
			// 初始化子级对象
			var $stepItems = jqobj.children('.search-step-item');
			if ($stepItems.length <= 0) {
				return false;
			}
			$.each($stepItems, function(index, item) {
				var stepItem = new StepItem(index);
				if (stepItem && stepItem.initialize($(this))) {
					invoke.stepItems.push(stepItem);
				}
			})
			
			// 创建双向链表
			$.each(this.stepItems, function(index, stepItem) {
				if (index == 0) {
					// 第一个子级
					if (invoke.stepItems.length != 1) {
						// 不止一个子级
						stepItem.next = invoke.stepItems[index + 1];
					}
				} else if ((index + 1) == invoke.stepItems.length) {
					// 最后一个子级
					stepItem.pre = invoke.stepItems[index - 1];
				} else {
					stepItem.pre = invoke.stepItems[index - 1];
					stepItem.next = invoke.stepItems[index + 1];
				}
			})
			
			// 添加头部标题
			jqobj.append('<div class="search-step-head"><ul class="search-step-titles"></ul></div>');
			// 添加内容容器
			jqobj.append('<div class="search-step-content"></div>');
			
			// 创建按钮
			this.createButton();
			
			// 渲染内容
			$.each(invoke.stepItems, function(index, stepItem) {
				// 创建标题
				var $title = $('<li class="search-step-title"><em class="search-step-number">' + (index + 1) + '</em><span class="search-step-name"></span></li>');
				$title.find('.search-step-name').html(stepItem.title || '第' + (index + 1) + '步');
				stepItem.titlejqobj = $title;
				jqobj.find('.search-step-titles').append(stepItem.titlejqobj);
				jqobj.find('.search-step-content').append(stepItem.jqobj);
				// 绑定点击事件
				$title.on('click', function(e) {
					if (!invoke.isTab) {
						return;
					}
					invoke.setCurrentStepItem(invoke.stepItems[index]);
				})
			})
			// 默认当前步骤
			this.setCurrentStepItem(this.stepItems[this.active]);
			return true;
		},
		/**
		 * 添加自定义按钮
		 * @param buttons 自定义按钮数组
		 * 		id ID，可以通过该值找到按钮对象
		 * 		name 名称
		 * 		addClass 添加class
		 * 		sort 排序
		 * 		click 单击函数
		 * 		layout 显示/隐藏函数
		 */
		addButtons : function(buttons) {
			buttons = buttons || [];
			buttons.reverse();
			this.toolButtons = this.toolButtons.concat(buttons);
			this.createButton();
			this.layoutButton();
		},
		/**
		 * 创建按钮
		 */
		createButton : function() {
			var invoke = this;
			var $footTool = this.jqobj.children('.search-step-foot');
			if ($footTool.length <= 0) {
				// 添加工具栏
				$footTool = $('<div class="search-step-foot"></div>');
				this.jqobj.append($footTool);
			} else {
				$footTool.empty();
			}
			this.toolButtonObjs = new Array();
			if (!this.toolButtons || this.toolButtons.length <= 0) {
				return;
			}
			// 排序
			this.toolButtons.sort(function(prebutton, nextbutton) {
				if (!(prebutton.sort >= 0 && nextbutton.sort >= 0)) {
					return false;
				}
				return prebutton.sort >= nextbutton.sort;
			})
			// 创建按钮
			$.each(this.toolButtons, function(index, toolButton) {
				var stepButton = new StepButton($footTool, $.extend({buttonDisabledIshide : invoke.buttonDisabledIshide}, toolButton, {sort : index}));
				// 绑定点击事件
				stepButton.jqobj.on('click', function() {
					searchComponents.applyMethod(toolButton.click, invoke, [invoke.currentStepItem]);
				})
				invoke.toolButtonObjs.push(stepButton);
			})
		},
		/**
		 * 调整按钮显示/隐藏
		 */
		layoutButton : function() {
			var invoke = this;
			$.each(invoke.toolButtonObjs, function(index, toolButton) {
				var enabled = (searchComponents.applyMethod(toolButton.layout, invoke, [invoke.currentStepItem]) != false ? true : false);
				toolButton.setEnabled(enabled);
			})
		},
		/**
		 * 获取按钮对象
		 * @param buttonid 按钮ID
		 * @return 按钮对象
		 */
		getToolButton : function(buttonid) {
			var buttonobj = null;
			$.each(this.toolButtonObjs, function(index, toolButton) {
				if (toolButton.id != buttonid) {
					return true;
				}
				buttonobj = toolButton;
				return false;
			})
			return buttonobj;
		},
		/**
		 * 设置当前步骤项
		 * @return 是否成功
		 */
		setCurrentStepItem : function(stepitem) {
			var invoke = this;
			if (this.currentStepItem) {
				if (!this.isTab && this.currentStepItem.index < stepitem.index && !new Form(this.currentStepItem.id).validate()) {
					// 引导操作并且下一步时，校验表单
					return false;
				}
				// 即将离开页面判断
				var isleave = searchComponents.applyMethod(this.currentStepItem.viewwillleave, this, [this.currentStepItem]) != false ? true : false;
				if (!isleave) {
					return false;
				}
				this.currentStepItem.hide();
			}
			// 即将进入页面判断
			var isenter = searchComponents.applyMethod(stepitem.viewwillenter, this, [stepitem]) != false ? true : false;
			if (!isenter && this.currentStepItem) {
				return false;
			}
			
			this.jqobj.find('.search-step-title').removeClass('search-step-title-before search-step-title-current search-step-title-after');
			// 之前的标题
			for (var i = 0; i < stepitem.index; i++) {
				invoke.stepItems[i].titlejqobj.addClass('search-step-title-before');
			}
			// 之后的标题
			for (var i = (this.stepItems.length - 1); i > stepitem.index; i--) {
				invoke.stepItems[i].titlejqobj.addClass('search-step-title-after');
			}
			if (this.currentStepItem) {
				// 已经离开页面回调
				searchComponents.applyMethod(this.currentStepItem.viewdidleave, this, [this.currentStepItem]);
			}
			this.currentStepItem = stepitem;
			this.currentStepItem.titlejqobj.addClass('search-step-title-current');
			this.currentStepItem.show();
			this.layoutButton();
			// 已经进入页面回调
			searchComponents.applyMethod(stepitem.viewdidenter, this, [stepitem]);
			return true;
		},
		/**
		 * 获取内容项
		 * @param stepid 内容项ID
		 * @return 内容对象
		 */
		getStepItem : function(stepid) {
			var stepobj = null;
			$.each(this.stepItems, function(index, stepItem) {
				if (stepItem.id != stepid) {
					return true;
				}
				stepobj = stepItem;
				return false;
			})
			return stepobj;
		},
		/**
		 * 表单验证
		 */
		validate : function() {
			var invoke = this;
			// 验证当前页面
			var validateTab = (this.validateTab != null ? (this.validateTab + '').split(',') : null);
			var currentForm = new Form(this.currentStepItem.id);
			if ((validateTab == null || validateTab.indexOf(this.currentStepItem.index + '') != -1)) {
				if (this.currentStepItem.validate) {
					if (searchComponents.applyMethod(this.currentStepItem.validate, this, [this.currentStepItem]) == false) {
						return false;
					}
				} else {
					if (!currentForm.validate()) {
						return false;
					}
				}
			}
			var validate = true;
			$.each(this.stepItems, function(index, stepitem) {
				if (invoke.currentStepItem.id == stepitem.id) {
					return validate;
				}
				if (!(validateTab == null || validateTab.indexOf(stepitem.index + '') != -1)) {
					return validate;
				}
				var form = new Form(stepitem.id);
				if (stepitem.validate) {
					if (searchComponents.applyMethod(stepitem.validate, invoke, [stepitem]) == false) {
						validate = false;
						invoke.setCurrentStepItem(stepitem);
					}
				} else {
					if (!form.validate()) {
						validate = false;
						invoke.setCurrentStepItem(stepitem);
					}
				}
				return validate;
			})
			return validate;
		}
	});
	// 选项卡-结束
	// 选项卡按钮-开始
	function StepButton(parentjqobj, options) {
		// 配置项
		options = options || {};
		// 父级jQuery对象
		this.parentjqobj = parentjqobj;
		// ID
		this.id = options.id;
		// 名称
		this.name = options.name;
		// 样式
		this.addClass = options.addClass;
		// 排序
		this.sort = options.sort;
		// 点击
		this.click = options.click;
		// 布局
		this.layout = options.layout;
		// 禁用时隐藏
		this.buttonDisabledIshide = options.buttonDisabledIshide;
		// 隐藏属性
		// 是否启用
		this._enabled = true;
		// 初始化
		this.init();
		return this;
	}
	StepButton.prototype = {
		// 构造函数
		consructor : StepButton,
		// 初始化
		init : function() {
			var invoke = this;
			var $button = $('<button type="button"></button>');
			$button.addClass(this.addClass).html(this.name);
			this.parentjqobj.append($button);
			this.jqobj = $button;
			return true;
		},
		/**
		 * 启用/禁用按钮
		 * @param enabled 启用/禁用
		 * @param isalways 总是该状态
		 */
		setEnabled : function(enabled, isalways) {
			if (isalways) {
				this._enabled = enabled;
			}
			if (enabled && this._enabled) {
				if (this.buttonDisabledIshide) {
					this.jqobj.show();
				}
				this.jqobj.removeClass('disabled');
			} else {
				if (this.buttonDisabledIshide) {
					this.jqobj.hide();
				}
				this.jqobj.addClass('disabled');
			}
		},
		/**
		 * 更改配置属性
		 * @param options 配置项
		 */
		setOptions : function(options) {
			var invoke = this;
			options = options || {};
			for (var key in options) {
				invoke[key] = options[key];
			}
		}
	}
	// 选项卡按钮-结束
	// 选项卡项-开始
	function StepItem(index) {
		// 索引
		this.index = index;
		// 上一个节点
		this.pre = null;
		// 下一个节点
		this.next = null;
		// 可配置属性
		this._prototypes = {
			// 标题
			title : null,
			// 即将离开回调；返回false将不会切换页面
			func_viewwillleave : null,
			// 即将进入回调；返回false将不会切换页面，初始化时无效
			func_viewwillenter : null,
			// 已经离开回调
			func_viewdidleave : null,
			// 已经进入回调
			func_viewdidenter : null,
			// 表单自定义校验
			func_validate : null
		};
	}
	// 选项卡项函数
	StepItem.prototype = $.extend(new Control(), {
		// 构造函数
		consructor : StepItem,
		// 初始化
		initialize : function(jqobj) {
			var invoke = this;
			var id = jqobj.attr('id');
			if (!id) {
				jqobj.attr('id', 'stepitem' + this.index);
			}
			if (!Control.prototype.initialize.call(invoke, jqobj)) return false;
			
			this.hide();
			return true;
		},
		// 显示内容
		show : function() {
			this.jqobj.show();
		},
		// 隐藏内容
		hide : function() {
			this.jqobj.hide();
		}
	});
	// 选项卡项-结束
}

// search工具集
var SearchUtils = new function() {
	/**
	 * 多个选项列表选择指定索引项
	 * @param searchObj search对象
	 * @param dataIndex 选项索引
	 */
	this.selecteds = function(searchObjs, dataIndex) {
		var invoke = this;
		$.each(searchObjs, function() {
			invoke.selected(this, dataIndex);
		})
	},
	/**
	 * 选项列表选择指定索引项
	 * @param searchObj search对象
	 * @param dataIndex 选项索引
	 * @return 是否成功
	 */
	this.selected = function(searchObj, dataIndex) {
		dataIndex = dataIndex || 0;
		if (!searchObj) {
			// search对象为空
			return false;
		}
		// 选项数据
		var selectData = null;
		if (typeof(searchObj.getData) == 'function') {
			selectData = searchObj.getData();
		} else {
			selectData = new Array();
			if (searchObj.control.hasClass('search-textradio')) {
				$.each(searchObj._itemRecords, function() {
					selectData.push(this);
				})
			} else if (searchObj.control.hasClass('search-treeselect')) {
				selectData = searchObj._data;
			}
		}
		if (!selectData || selectData.length <= dataIndex) {
			// 没有数据
			return false;
		}
		searchObj.setValue(selectData[dataIndex][searchObj.idField]);
		return true;
	},
	/**
	 * 添加选择列表默认选择指定索引项
	 * @param searchObjs search对象数组
	 * @param dataIndex 选项索引
	 * @return 是否成功
	 */
	this.addLoadedSelecteds = function(searchObjs, dataIndex) {
		if (!searchObjs || searchObjs.length <= 0) {
			// search对象数组为空
			return false;
		}
		var invoke = this;
		$.each(searchObjs, function(index, searchObj) {
			var originalLoaded = searchObj.loaded;
			searchObj.loaded = function(e) {
				invoke.selected(searchObj, dataIndex);
				if (!originalLoaded || typeof(originalLoaded) != 'function') {
					return;
				}
				originalLoaded.call(searchObj, e);
			}
		})
		return true;
	},
	/**
	 * 表格添加选择行改变事件
	 * @param datagrid 表格对象
	 * @param selectchaned 前置函数
	 * @return 是否成功
	 */
	this.addDatagridSelectchanged = function(datagrid, selectchaned) {
		if (!datagrid) {
			// search对象为空
			return false;
		}
		var originalSelectchanged = datagrid.selectchanged;
		datagrid.selectchanged = function(e) {
			if (selectchaned && typeof(selectchaned) == 'function') {
				selectchaned.call(datagrid, e);
			}
			if (originalSelectchanged && typeof(originalSelectchanged) == 'function') {
				originalSelectchanged.call(datagrid, e);
			}
		}
		return true;
	},
	/**
	 * 提示弹窗封装
	 * @param options 配置选项，当是字符串时，直接错误提示
	 * 			code 弹窗编码
	 * 			message 弹窗内容
	 */
	this.msg = function(options) {
		options = options || {};
		if (typeof options == 'string') {
			top.search.error({content : options});
			return;
		}
		switch (options.code) {
		case 3:
			top.search.warn({content : options.message});
			break;
		case 4:
			top.search.error({content : options.message});
			break;
		default:
			top.search.info({content : options.message});
			break;
		}
	}
}